package com.suning.sawp.service.util;

import java.io.Serializable;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.google.common.base.Charsets;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.suning.framework.sedis.JedisAction;
import com.suning.framework.sedis.JedisClient;
import com.suning.sawp.constants.CacheKeyConstants;

import redis.clients.jedis.Jedis;

/**
 * Redis缓存工具类
 * 
 * @author 88253542
 */
@Component("cacheUtils")
public class RedisCacheUtils {
    /**
     * 日期格式
     */
    private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
    /**
     * logger
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(RedisCacheUtils.class);

    /**
     * 
     */
    public static final int REDIS_TIME_ONE_DAY = 24 * 60 * 60;

    private static Gson THE_GSON = new GsonBuilder().setDateFormat(DATE_FORMAT).enableComplexMapKeySerialization()
            .create();

    /**
     * 将序列化对象值value关联到key， 如果key已经持有其他值，SET就覆写旧值
     * 
     * @param key 缓存key
     * @param value 缓存的对象
     */
    public void hset(String key, String field, Object value) {
        // 缓存管理器中取出缓存配置
        try {
            Gson gson = new GsonBuilder().setDateFormat(DATE_FORMAT).enableComplexMapKeySerialization().create();
            boolean exist = true;
            long leftTime = ttl(key);
            if (leftTime < 0) {
                // 过期时间小于0说明key不存在
                exist = false;
            }
            // 缓存配置不为空且有效则设置业务缓存
            hset(key, field, gson.toJson(value));
            if (!exist) {
                // 有效时间不为0且key为新插入则设置业务缓存的有效时间
                expire(key, CacheKeyConstants.COMMON_EXPIRE_TIME);
            }
        } catch (Exception e) {
            LOGGER.error("cache error", e);
        }
    }

    /**
     * 返回哈希表key中给定域field的值
     * 
     * @param key 缓存key
     * @param field key中的域
     * @param type 被缓存的对象类型
     * @return T 被缓存的对象
     */
    @SuppressWarnings("unchecked")
    public <T extends Serializable> T hget(String key, String field, Type type) {
        // 缓存管理器中取出缓存配置
        try {
            Gson gson = new GsonBuilder().setDateFormat(DATE_FORMAT).enableComplexMapKeySerialization().create();

            // 缓存配置不为空且有效则获取业务缓存
            String str = hget(key, field);
            if (StringUtils.isBlank(str)) {
                return null;
            }
            // 转换成需要的对象
            return (T) gson.fromJson(str, type);

        } catch (Exception e) {
            LOGGER.error("hget error", e);
            return null;
        }
    }

    /**
     * 将序列化对象值value关联到key， 如果key已经持有其他值，SET就覆写旧值
     * 
     * @param key 缓存key
     * @param value 缓存的对象
     */
    public void hsetWithMyExpireTime(String key, String field, Object value, int expireTime) {
        // 缓存管理器中取出缓存配置
        try {
            Gson gson = new GsonBuilder().setDateFormat(DATE_FORMAT).enableComplexMapKeySerialization().create();
            boolean exist = true;
            long leftTime = ttl(key);
            if (leftTime < 0) {
                // 过期时间小于0说明key不存在
                exist = false;
            }
            // 缓存配置不为空且有效则设置业务缓存
            hset(key, field, gson.toJson(value));
            if (!exist) {
                // 有效时间不为0且key为新插入则设置业务缓存的有效时间
                expire(key, expireTime);
            }
        } catch (Exception e) {
            LOGGER.error("cache error", e);
        }
    }

    /**
     * 清除业务缓存的数据
     * 
     * @param cacheKey 缓存配置
     */
    public void clearCacheData(String cacheKey) {
        del(cacheKey);
    }

    /**
     * 清除业务缓存的数据
     * 
     * @param key 缓存key
     * @param field 缓存field
     */
    public void clearCacheData(String key, String field) {
        hdel(key, field);
    }

    @Autowired
    private JedisClient jedisClient;

    public JedisClient getJedisClient() {
        return jedisClient;
    }

    public void setJedisClient(JedisClient jedisClient) {
        this.jedisClient = jedisClient;
    }

    public String set(final String key, final String value) {
        return jedisClient.execute(new JedisAction<String>() {
            @Override
            public String doAction(Jedis jedis) {
                return jedis.set(key, value);
            }
        });
    }

    public String get(final String key) {
        return jedisClient.execute(new JedisAction<String>() {
            @Override
            public String doAction(Jedis jedis) {
                return jedis.get(key);
            }
        });
    }

    @SuppressWarnings("unchecked")
    public <T extends Serializable> T get(String key, Type type) {
        try {
            // 缓存配置不为空且有效则获取业务缓存
            String str = get(key);
            if (StringUtils.isBlank(str)) {
                return null;
            }
            // 转换成需要的对象
            return (T) THE_GSON.fromJson(str, type);
        } catch (Exception e) {
            LOGGER.error("hget error", e);
            return null;
        }
    }

    public Long hset(final String key, final String field, final String value) {
        return jedisClient.execute(new JedisAction<Long>() {
            @Override
            public Long doAction(Jedis jedis) {
                return jedis.hset(key, field, value);
            }
        });
    }

    public String setex(final String key, final int seconds, final String value) {
        return jedisClient.execute(new JedisAction<String>() {
            @Override
            public String doAction(Jedis jedis) {
                return jedis.setex(key, seconds, value);
            }
        });
    }

    public String setex(String key, int seconds, Object value) {
        return setex(key, seconds, THE_GSON.toJson(value));
    }

    /*
     * (non-Javadoc)
     * @see com.suning.ebuy.wd.cache.RedisClient#setex(java.lang.String, int, byte[])
     */
    public byte[] setex(final String key, final int seconds, final byte[] value) {
        return jedisClient.execute(new JedisAction<byte[]>() {
            @Override
            public byte[] doAction(Jedis jedis) {
                return jedis.setex(key.getBytes(Charsets.UTF_8), seconds, value).getBytes(Charsets.UTF_8);
            }
        });
    }

    public Long del(final String key) {
        return jedisClient.execute(new JedisAction<Long>() {
            @Override
            public Long doAction(Jedis jedis) {
                return jedis.del(key);
            }
        });
    }

    public Boolean exists(final String key) {
        return jedisClient.execute(new JedisAction<Boolean>() {
            @Override
            public Boolean doAction(Jedis jedis) {
                return jedis.exists(key);
            }
        });
    }

    public Long expire(final String key, final int seconds) {
        return jedisClient.execute(new JedisAction<Long>() {
            @Override
            public Long doAction(Jedis jedis) {
                return jedis.expire(key, seconds);
            }
        });
    }

    public String hget(final String key, final String field) {
        return jedisClient.execute(new JedisAction<String>() {
            @Override
            public String doAction(Jedis jedis) {
                return jedis.hget(key, field);
            }
        });
    }

    public Boolean hexists(final String key, final String field) {
        return jedisClient.execute(new JedisAction<Boolean>() {
            @Override
            public Boolean doAction(Jedis jedis) {
                return jedis.hexists(key, field);
            }
        });
    }

    public Long hdel(final String key, final String... fields) {
        return jedisClient.execute(new JedisAction<Long>() {
            @Override
            public Long doAction(Jedis jedis) {
                return jedis.hdel(key, fields);
            }
        });
    }

    public Set<String> hkeys(final String key) {
        return jedisClient.execute(new JedisAction<Set<String>>() {
            @Override
            public Set<String> doAction(Jedis jedis) {
                return jedis.hkeys(key);
            }
        });
    }

    public List<String> hvals(final String key) {
        return jedisClient.execute(new JedisAction<List<String>>() {
            @Override
            public List<String> doAction(Jedis jedis) {
                return jedis.hvals(key);
            }
        });
    }

    public Map<String, String> hgetAll(final String key) {
        return jedisClient.execute(new JedisAction<Map<String, String>>() {
            @Override
            public Map<String, String> doAction(Jedis jedis) {
                return jedis.hgetAll(key);
            }
        });
    }

    public String hmset(final String key, final Map<String, String> map) {
        return jedisClient.execute(new JedisAction<String>() {
            @Override
            public String doAction(Jedis jedis) {
                return jedis.hmset(key, map);
            }
        });
    }

    public List<String> hmget(final String key, final String... fields) {
        return jedisClient.execute(new JedisAction<List<String>>() {
            @Override
            public List<String> doAction(Jedis jedis) {
                return jedis.hmget(key, fields);
            }
        });
    }

    public Long expireAt(final String key, final long seconds) {
        return jedisClient.execute(new JedisAction<Long>() {
            @Override
            public Long doAction(Jedis jedis) {
                return jedis.expireAt(key, seconds);
            }
        });
    }

    public Long ttl(final String key) {
        return jedisClient.execute(new JedisAction<Long>() {
            @Override
            public Long doAction(Jedis jedis) {
                return jedis.ttl(key);
            }
        });
    }

    /*
     * (non-Javadoc)
     * @see com.suning.ebuy.wd.cache.RedisClient#keys(java.lang.String)
     */
    public Set<String> keys(final String partten) {
        return jedisClient.execute(new JedisAction<Set<String>>() {
            @Override
            public Set<String> doAction(Jedis jedis) {
                return jedis.keys(partten);
            }
        });
    }

    /*
     * (non-Javadoc)
     * @see com.suning.ebuy.wd.cache.RedisClient#get(java.lang.String)
     */
    public byte[] getByte(final String key) {
        return jedisClient.execute(new JedisAction<byte[]>() {
            @Override
            public byte[] doAction(Jedis jedis) {
                return jedis.get(key.getBytes(Charsets.UTF_8));
            }
        });
    }

    /*
     * (non-Javadoc)
     * @see com.suning.ebuy.wd.cache.RedisClient#set(java.lang.String, byte[])
     */
    public String set(final String key, final byte[] value) {
        return jedisClient.execute(new JedisAction<String>() {
            @Override
            public String doAction(Jedis jedis) {
                return jedis.set(key.getBytes(Charsets.UTF_8), value);
            }
        });
    }

    /**
     * 功能描述: <br>
     * 对value值逐次加1
     */
    public Long incr(final String key) {
        return jedisClient.execute(new JedisAction<Long>() {
            @Override
            public Long doAction(Jedis jedis) {
                return jedis.incr(key);
            }
        });
    }

    /**
     * 功能描述: <br>
     * 对value值逐次减1
     */
    public Long decr(final String key) {
        return jedisClient.execute(new JedisAction<Long>() {
            @Override
            public Long doAction(Jedis jedis) {
                return jedis.decr(key);
            }
        });
    }

    public Long lpush(final String key, final String value) {
        return jedisClient.execute(new JedisAction<Long>() {
            @Override
            public Long doAction(Jedis jedis) {
                return jedis.lpush(key, value);
            }
        });
    }

    public String lpop(final String key) {
        return jedisClient.execute(new JedisAction<String>() {
            @Override
            public String doAction(Jedis jedis) {
                return jedis.lpop(key);
            }
        });
    }

    public List<String> lrange(final String key, final long start, final long end) {
        return jedisClient.execute(new JedisAction<List<String>>() {
            @Override
            public List<String> doAction(Jedis jedis) {
                return jedis.lrange(key, start, end);
            }
        });
    }

    /**
     * 
     * 功能描述: 往key记录set结构的元素，自动去重<br>
     * 
     * @param key
     * @param members
     * @return
     */
    public Long sadd(final String key, final String... members) {
        return jedisClient.execute(new JedisAction<Long>() {
            @Override
            public Long doAction(Jedis jedis) {
                return jedis.sadd(key, members);
            }
        });
    }

    /**
     * 
     * 功能描述: 判断key中是否存在元素member<br>
     * 
     * @param key
     * @param member
     * @return
     */
    public Boolean sismember(final String key, final String member) {
        return jedisClient.execute(new JedisAction<Boolean>() {
            @Override
            public Boolean doAction(Jedis jedis) {
                return jedis.sismember(key, member);
            }
        });
    }

    /**
     * 
     * 功能描述: 返回所有的元素set集合<br>
     * 
     * @param key
     * @return
     */
    public Set<String> smembers(final String key) {
        return jedisClient.execute(new JedisAction<Set<String>>() {
            public Set<String> doAction(Jedis jedis) {
                return jedis.smembers(key);
            }
        });
    }
}
